import sys
import sqlite3
from PySide6.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton,
                               QTextEdit, QTableWidget, QTableWidgetItem, QCheckBox, QStackedWidget,
                               QInputDialog, QComboBox, QLineEdit, QGroupBox, QHeaderView, QAbstractItemView,
                               QMessageBox)
from PySide6.QtGui import QFont
from PySide6.QtCore import Qt, QDateTime
from loguru import logger
import os

# 日志文件路径
LOG_FILE_PATH = "../logs/tsad_system.log"

# 模拟外部检测接口
def external_detection_api(model_name, params):
    """模拟异常检测API，返回检测结果"""
    result = f"使用 {model_name} 模型，参数 {params} 进行检测，检测结果：正常"
    return result

class LogHandler:
    """日志处理类，用于将loguru日志显示到UI"""
    def __init__(self, log_text_edit):
        self.log_text_edit = log_text_edit

    def write(self, message):
        """将日志消息添加到文本编辑控件中"""
        self.log_text_edit.append(message.strip())

class TSADSystem(QWidget):
    """时序异常检测系统主窗口"""
    def __init__(self):
        super().__init__()

        # 模型参数映射（模型名称 -> 参数列表）
        self.model_params_map = {
            "TranAD": ["窗口大小", "预测步长", "隐藏维度", "注意力头数", "层数", "学习率"],
            "InterFusion": ["嵌入维度", "编码器层数", "解码器层数", "融合因子", "阈值", "批量大小"],
        }

        # 初始化空的检测历史数据
        self.detection_history_data = []

        # 连接SQLite数据库
        self.conn = sqlite3.connect('../data/models.db')
        self.cursor = self.conn.cursor()
        self.create_models_table()

        # 设置窗口标题和大小
        self.setWindowTitle("TSAD系统")
        self.setFixedSize(800, 600)

        # 统一字体设置
        self.font = QFont("Arial", 12)

        # 左侧导航栏布局
        left_layout = QVBoxLayout()
        left_layout.setAlignment(Qt.AlignTop)

        # 导航按钮
        self.home_button = QPushButton("首页")
        self.model_button = QPushButton("模型")
        self.anomaly_detection_button = QPushButton("异常检测")
        self.detection_history_button = QPushButton("检测历史")

        self.home_button.setStyleSheet("background-color: #007acc; color: white;")
        self.home_button.clicked.connect(lambda: self.show_page(0))
        self.model_button.clicked.connect(lambda: self.show_page(1))
        self.anomaly_detection_button.clicked.connect(lambda: self.show_page(2))
        self.detection_history_button.clicked.connect(lambda: self.show_page(3))

        self.home_button.setFont(self.font)
        self.model_button.setFont(self.font)
        self.anomaly_detection_button.setFont(self.font)
        self.detection_history_button.setFont(self.font)

        left_layout.addWidget(self.home_button)
        left_layout.addWidget(self.model_button)
        left_layout.addWidget(self.anomaly_detection_button)
        left_layout.addWidget(self.detection_history_button)

        # 创建 QStackedWidget 来管理不同的页面
        self.stacked_widget = QStackedWidget()
        self.home_widget = self.create_home_layout()
        self.stacked_widget.addWidget(self.home_widget)
        self.model_widget = self.create_model_layout()
        self.stacked_widget.addWidget(self.model_widget)
        self.anomaly_detection_widget = self.create_anomaly_detection_layout()
        self.stacked_widget.addWidget(self.anomaly_detection_widget)
        self.detection_history_widget = self.create_detection_history_layout()
        self.stacked_widget.addWidget(self.detection_history_widget)

        # 整体布局
        main_layout = QHBoxLayout()
        main_layout.addLayout(left_layout)
        main_layout.addWidget(self.stacked_widget)
        self.setLayout(main_layout)

        # 加载历史日志
        self.load_history_logs()

        # 添加UI日志处理器
        logger.add(LogHandler(self.log_text_edit).write, format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}")

        # 配置loguru将日志写入文件
        logger.add(LOG_FILE_PATH, rotation="10 MB", retention="7 days", level="INFO")

        # 初始化日志
        logger.info("TSAD系统已启动")
        self.update_model_count()
        self.update_detection_count()

    def load_history_logs(self):
        """加载历史日志文件内容到UI"""
        try:
            if os.path.exists(LOG_FILE_PATH):
                with open(LOG_FILE_PATH, 'r', encoding='utf-8') as f:
                    logs = f.read()
                    self.log_text_edit.setText(logs)
        except Exception as e:
            logger.error(f"加载历史日志失败: {str(e)}")

    def create_models_table(self):
        """创建模型表"""
        try:
            self.cursor.execute('''
                CREATE TABLE IF NOT EXISTS models (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    model_name TEXT,
                    create_time TEXT,
                    description TEXT
                )
            ''')
            self.conn.commit()
            logger.info("模型表已创建/验证")
        except Exception as e:
            logger.error(f"创建模型表失败: {str(e)}")

    def create_home_layout(self):
        """创建首页布局"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setContentsMargins(15, 15, 15, 15)
        layout.setSpacing(20)

        # 统计信息区域
        stats_group = QGroupBox("系统统计")
        stats_group.setFont(self.font)
        stats_layout = QHBoxLayout(stats_group)
        stats_layout.setSpacing(20)

        # 模型统计
        model_stats = QWidget()
        model_stats_layout = QVBoxLayout(model_stats)
        model_stats_layout.setAlignment(Qt.AlignCenter)

        self.model_count_title = QLabel("模型数量")
        self.model_count_title.setFont(QFont("Arial", 14, QFont.Bold))
        self.model_count_title.setAlignment(Qt.AlignCenter)

        self.model_count_label = QLabel("0")
        self.model_count_label.setStyleSheet("""
            QLabel {
                border: 2px solid #007acc;
                border-radius: 50%;
                padding: 40px;
                background-color: #f0f8ff;
                color: #007acc;
                font-size: 24px;
                font-weight: bold;
            }
        """)
        self.model_count_label.setAlignment(Qt.AlignCenter)
        self.model_count_label.setMinimumSize(120, 120)

        model_stats_layout.addWidget(self.model_count_title)
        model_stats_layout.addWidget(self.model_count_label)

        # 检测统计
        detection_stats = QWidget()
        detection_stats_layout = QVBoxLayout(detection_stats)
        detection_stats_layout.setAlignment(Qt.AlignCenter)

        self.detection_count_title = QLabel("检测次数")
        self.detection_count_title.setFont(QFont("Arial", 14, QFont.Bold))
        self.detection_count_title.setAlignment(Qt.AlignCenter)

        self.detection_count_label = QLabel("0")
        self.detection_count_label.setStyleSheet("""
            QLabel {
                border: 2px solid #228B22;
                border-radius: 50%;
                padding: 40px;
                background-color: #F0FFF0;
                color: #228B22;
                font-size: 24px;
                font-weight: bold;
            }
        """)
        self.detection_count_label.setAlignment(Qt.AlignCenter)
        self.detection_count_label.setMinimumSize(120, 120)

        detection_stats_layout.addWidget(self.detection_count_title)
        detection_stats_layout.addWidget(self.detection_count_label)

        stats_layout.addWidget(model_stats)
        stats_layout.addWidget(detection_stats)

        # 系统日志区域
        log_group = QGroupBox("系统日志")
        log_group.setFont(self.font)
        log_layout = QVBoxLayout(log_group)

        self.log_text_edit = QTextEdit()
        self.log_text_edit.setPlaceholderText("系统日志将显示在这里...")
        self.log_text_edit.setReadOnly(True)
        self.log_text_edit.setFont(self.font)

        log_layout.addWidget(self.log_text_edit)

        layout.addWidget(stats_group)
        layout.addWidget(log_group)

        return widget

    def update_model_count(self):
        """更新模型数量统计"""
        try:
            self.cursor.execute("SELECT COUNT(*) FROM models")
            count = self.cursor.fetchone()[0]
            self.model_count_label.setText(str(count))
        except Exception as e:
            logger.error(f"更新模型数量失败: {str(e)}")

    def update_detection_count(self):
        """更新检测次数统计"""
        count = len(self.detection_history_data)
        self.detection_count_label.setText(str(count))

    def create_model_layout(self):
        """创建模型管理布局"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setContentsMargins(15, 15, 15, 15)
        layout.setSpacing(15)

        # 操作按钮区域
        btn_layout = QHBoxLayout()
        btn_layout.setSpacing(10)

        self.add_button = QPushButton("添加模型")
        self.modify_button = QPushButton("修改模型")
        self.delete_button = QPushButton("删除模型")

        self.add_button.setStyleSheet("background-color: #4CAF50; color: white;")
        self.modify_button.setStyleSheet("background-color: #2196F3; color: white;")
        self.delete_button.setStyleSheet("background-color: #F44336; color: white;")

        self.add_button.setFont(self.font)
        self.modify_button.setFont(self.font)
        self.delete_button.setFont(self.font)

        self.add_button.clicked.connect(self.add_model)
        self.modify_button.clicked.connect(self.modify_model)
        self.delete_button.clicked.connect(self.delete_model)

        btn_layout.addWidget(self.add_button)
        btn_layout.addWidget(self.modify_button)
        btn_layout.addWidget(self.delete_button)

        # 模型表格
        self.table = QTableWidget()
        self.table.setColumnCount(5)
        self.table.setHorizontalHeaderLabels(["选择", "序号", "模型名称", "创建时间", "描述"])
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.setFont(self.font)

        # 加载模型数据
        self.populate_model_table()

        layout.addLayout(btn_layout)
        layout.addWidget(self.table)

        return widget

    def create_anomaly_detection_layout(self):
        """创建异常检测布局"""
        widget = QWidget()
        layout = QHBoxLayout(widget)
        layout.setContentsMargins(15, 15, 15, 15)
        layout.setSpacing(20)

        # 左侧参数设置区域
        left_widget = QWidget()
        left_widget.setMinimumWidth(300)
        left_layout = QVBoxLayout(left_widget)
        left_layout.setSpacing(15)

        # 模型选择区域
        model_group = QGroupBox("模型选择")
        model_group.setFont(self.font)
        model_layout = QVBoxLayout(model_group)

        model_label = QLabel("选择检测模型:")
        model_label.setFont(self.font)
        self.model_combobox = QComboBox()
        self.model_combobox.setMinimumHeight(35)
        self.model_combobox.setFont(self.font)
        self.populate_model_combobox()

        # 连接模型选择变化信号
        self.model_combobox.currentTextChanged.connect(self.update_param_inputs)

        model_layout.addWidget(model_label)
        model_layout.addWidget(self.model_combobox)

        # 参数设置区域
        self.param_group = QGroupBox("参数设置")
        self.param_group.setFont(self.font)
        self.param_layout = QVBoxLayout(self.param_group)
        self.param_layout.setSpacing(10)

        # 结果显示区域
        result_group = QGroupBox("检测结果")
        result_group.setFont(self.font)
        result_layout = QVBoxLayout(result_group)

        self.detection_result_textedit = QTextEdit()
        self.detection_result_textedit.setPlaceholderText("检测结果将显示在这里...")
        self.detection_result_textedit.setReadOnly(True)
        self.detection_result_textedit.setFont(self.font)
        self.detection_result_textedit.setMinimumHeight(200)

        result_layout.addWidget(self.detection_result_textedit)

        # 按钮区域
        btn_layout = QHBoxLayout()
        self.detect_button = QPushButton("执行检测")
        self.detect_button.setMinimumHeight(40)
        self.detect_button.setStyleSheet("""
            QPushButton {
                background-color: #007acc;
                color: white;
                border-radius: 5px;
                font-size: 14px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #005fa3;
            }
            QPushButton:pressed {
                background-color: #004c80;
            }
        """)
        self.detect_button.setFont(QFont("Arial", 14, QFont.Bold))
        self.detect_button.clicked.connect(self.perform_detection)

        btn_layout.addStretch()
        btn_layout.addWidget(self.detect_button)
        btn_layout.addStretch()

        left_layout.addWidget(model_group)
        left_layout.addWidget(self.param_group)
        left_layout.addStretch()
        left_layout.addLayout(btn_layout)

        layout.addWidget(left_widget, 1)  # 调整左侧占比

        # 初始化参数输入框
        self.update_param_inputs(self.model_combobox.currentText())

        return widget

    def update_param_inputs(self, model_name):
        """根据选择的模型更新参数输入框"""
        # 清空现有参数输入框
        while self.param_layout.count():
            item = self.param_layout.takeAt(0)
            widget = item.widget()
            if widget:
                widget.deleteLater()

        # 获取该模型的参数列表
        params = self.model_params_map.get(model_name, [f"参数{i}" for i in range(1, 7)])

        # 创建新的参数输入框
        self.param_line_edits = []
        for param_name in params:
            label_widget = QLabel(param_name)
            label_widget.setStyleSheet("color: #007acc; font-weight: bold;")
            label_widget.setFont(self.font)
            self.param_layout.addWidget(label_widget)

            edit = QLineEdit()
            edit.setMinimumHeight(30)
            edit.setFont(self.font)
            self.param_layout.addWidget(edit)
            self.param_line_edits.append(edit)

    def create_detection_history_layout(self):
        """创建检测历史布局"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setContentsMargins(15, 15, 15, 15)
        layout.setSpacing(15)

        # 操作按钮区域
        btn_layout = QHBoxLayout()
        btn_layout.setSpacing(10)

        self.delete_history_button = QPushButton("删除选中记录")
        self.clear_history_button = QPushButton("清空所有记录")

        self.delete_history_button.setStyleSheet("background-color: #F44336; color: white;")
        self.clear_history_button.setStyleSheet("background-color: #FF9800; color: white;")

        self.delete_history_button.setFont(self.font)
        self.clear_history_button.setFont(self.font)

        self.delete_history_button.clicked.connect(self.delete_detection_history)
        self.clear_history_button.clicked.connect(self.clear_detection_history)

        btn_layout.addWidget(self.delete_history_button)
        btn_layout.addWidget(self.clear_history_button)

        # 历史记录表格
        self.history_table = QTableWidget()
        self.history_table.setColumnCount(6)
        self.history_table.setHorizontalHeaderLabels(["选择", "序号", "模型", "完成时间", "备注", "操作"])
        self.history_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.history_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)
        self.history_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.history_table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.history_table.setFont(self.font)

        # 加载历史记录
        self.update_detection_history_table()

        layout.addLayout(btn_layout)
        layout.addWidget(self.history_table)

        return widget

    def show_page(self, index):
        """显示指定页面并更新按钮样式"""
        self.stacked_widget.setCurrentIndex(index)
        # 重置所有按钮样式
        self.home_button.setStyleSheet("")
        self.model_button.setStyleSheet("")
        self.anomaly_detection_button.setStyleSheet("")
        self.detection_history_button.setStyleSheet("")
        # 设置当前选中按钮的样式
        if index == 0:
            self.home_button.setStyleSheet("background-color: #007acc; color: white;")
        elif index == 1:
            self.model_button.setStyleSheet("background-color: #007acc; color: white;")
        elif index == 2:
            self.anomaly_detection_button.setStyleSheet("background-color: #007acc; color: white;")
        elif index == 3:
            self.detection_history_button.setStyleSheet("background-color: #007acc; color: white;")

    def add_model(self):
        """添加新模型"""
        model_name, ok = QInputDialog.getText(self, "添加模型", "请输入模型名称:")
        if ok and model_name:
            try:
                create_time = QDateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss")
                description = "..."
                self.cursor.execute('''
                    INSERT INTO models (model_name, create_time, description)
                    VALUES (?,?,?)
                ''', (model_name, create_time, description))
                self.conn.commit()
                self.populate_model_table()
                self.update_model_count()
                self.populate_model_combobox()

                # 如果新添加的模型不在参数映射中，添加默认参数
                if model_name not in self.model_params_map:
                    self.model_params_map[model_name] = [f"参数{i}" for i in range(1, 7)]

                logger.info(f"添加模型: {model_name}")
            except Exception as e:
                logger.error(f"添加模型失败: {str(e)}")
                QMessageBox.critical(self, "错误", f"添加模型失败: {str(e)}")

    def modify_model(self):
        """修改模型名称"""
        selected_row = self.get_selected_row()
        if selected_row is not None:
            model_id = selected_row[0]
            current_name = selected_row[1]
            new_model_name, ok = QInputDialog.getText(self, "修改模型", "请输入新的模型名称:", text=current_name)
            if ok and new_model_name and new_model_name != current_name:
                try:
                    self.cursor.execute('''
                        UPDATE models
                        SET model_name =?
                        WHERE id =?
                    ''', (new_model_name, model_id))
                    self.conn.commit()
                    self.populate_model_table()
                    self.populate_model_combobox()

                    # 更新参数映射
                    if current_name in self.model_params_map:
                        self.model_params_map[new_model_name] = self.model_params_map.pop(current_name)

                    logger.info(f"修改模型: {current_name} -> {new_model_name}")
                except Exception as e:
                    logger.error(f"修改模型失败: {str(e)}")
                    QMessageBox.critical(self, "错误", f"修改模型失败: {str(e)}")

    def delete_model(self):
        """删除选中的模型"""
        selected_row = self.get_selected_row()
        if selected_row is not None:
            model_id = selected_row[0]
            model_name = selected_row[1]

            # 确认对话框
            reply = QMessageBox.question(self, "确认删除", f"确定要删除模型 {model_name} 吗？",
                                         QMessageBox.Yes | QMessageBox.No)
            if reply == QMessageBox.Yes:
                try:
                    self.cursor.execute("DELETE FROM models WHERE id =?", (model_id,))
                    self.conn.commit()
                    self.populate_model_table()
                    self.update_model_count()
                    self.populate_model_combobox()

                    # 从参数映射中移除该模型
                    if model_name in self.model_params_map:
                        del self.model_params_map[model_name]

                    logger.info(f"删除模型: {model_name}")
                except Exception as e:
                    logger.error(f"删除模型失败: {str(e)}")
                    QMessageBox.critical(self, "错误", f"删除模型失败: {str(e)}")

    def get_selected_row(self):
        """获取选中的表格行数据"""
        selected_items = self.table.selectedItems()
        if not selected_items:
            QMessageBox.warning(self, "警告", "请选择一个模型记录。")
            return None
        row = selected_items[0].row()
        model_id = int(self.table.item(row, 1).text())
        model_name = self.table.item(row, 2).text()
        return model_id, model_name

    def populate_model_table(self):
        """填充模型表格数据"""
        self.table.setRowCount(0)
        try:
            self.cursor.execute("SELECT id, model_name, create_time, description FROM models")
            rows = self.cursor.fetchall()
            for row_index, row_data in enumerate(rows):
                self.table.insertRow(row_index)
                checkbox = QCheckBox()
                self.table.setCellWidget(row_index, 0, checkbox)
                for col_index, data in enumerate(row_data, start=1):
                    item = QTableWidgetItem(str(data))
                    self.table.setItem(row_index, col_index, item)
        except Exception as e:
            logger.error(f"加载模型数据失败: {str(e)}")

    def populate_model_combobox(self):
        """填充模型选择下拉框"""
        self.model_combobox.clear()
        try:
            self.cursor.execute("SELECT model_name FROM models")
            rows = self.cursor.fetchall()
            for row in rows:
                self.model_combobox.addItem(row[0])
        except Exception as e:
            logger.error(f"加载模型到下拉框失败: {str(e)}")

    def perform_detection(self):
        """执行异常检测"""
        model_name = self.model_combobox.currentText()
        if not model_name:
            QMessageBox.warning(self, "警告", "请先添加模型")
            return

        params = {}
        for label_widget, edit in zip(self.param_layout.children()[::2], self.param_line_edits):
            param_name = label_widget.text()
            param_value = edit.text()
            params[param_name] = param_value

        result = external_detection_api(model_name, params)
        self.detection_result_textedit.setText(result)

        # 更新检测历史记录
        new_record = {
            "序号": len(self.detection_history_data) + 1,
            "模型": model_name,
            "完成时间": QDateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss"),
            "备注": result.split("：")[-1],
            "操作": "详情"
        }
        self.detection_history_data.append(new_record)
        self.update_detection_count()
        self.update_detection_history_table()

        logger.info(f"执行检测: {model_name}, 参数: {params}")

    def update_detection_history_table(self):
        """更新检测历史表格"""
        self.history_table.setRowCount(0)
        for row_index, record in enumerate(self.detection_history_data):
            self.history_table.insertRow(row_index)
            checkbox = QCheckBox()
            self.history_table.setCellWidget(row_index, 0, checkbox)
            for col_index, key in enumerate(["序号", "模型", "完成时间", "备注", "操作"]):
                item = QTableWidgetItem(str(record[key]))
                self.history_table.setItem(row_index, col_index + 1, item)

    def delete_detection_history(self):
        """删除选中的检测历史记录"""
        selected_rows = []
        for row in range(self.history_table.rowCount()):
            checkbox = self.history_table.cellWidget(row, 0)
            if checkbox and checkbox.isChecked():
                selected_rows.append(row)

        if not selected_rows:
            QMessageBox.warning(self, "警告", "请选择要删除的记录。")
            return

        for row in reversed(selected_rows):
            del self.detection_history_data[row]

        self.update_detection_count()
        self.update_detection_history_table()
        logger.info("删除选中的检测历史记录")

    def clear_detection_history(self):
        """清空所有检测历史记录"""
        reply = QMessageBox.question(self, "确认清空", "确定要清空所有检测历史记录吗？",
                                     QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            self.detection_history_data = []
            self.update_detection_count()
            self.update_detection_history_table()
            logger.info("清空所有检测历史记录")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = TSADSystem()
    window.show()
    sys.exit(app.exec())